Avage reaalajas funktsionaalsus oma Django projektides Django Channelsi ja WebSocketide abil. See põhjalik juhend pakub samm-sammulist ülevaadet, parimaid tavasid ja edasijõudnute tehnikaid.
Python Django Channels: Põhjalik juhend WebSocketi implementeerimiseks
Tänapäeva dünaamilisel veebimaastikul pole reaalajas rakendused enam luksus, vaid vajadus. Alates reaalajas vestlusrakendustest ja koostöö-redigeerimisvahenditest kuni online-mängude ja reaalajas andmete armatuurlaudadeni – nõudlus kohese suhtluse ja uuenduste järele kasvab pidevalt. Õnneks pakub Pythoni Django raamistik võimsa lahenduse selliste rakenduste ehitamiseks: Django Channels.
See juhend pakub põhjalikku ülevaadet Django Channelsist ja selle WebSocketi implementeerimisest. Süveneme põhimõistetesse, käime läbi praktilise näite ja arutame edasijõudnute tehnikaid, mis aitavad teil luua Djangoga robustseid ja skaleeritavaid reaalajas rakendusi.
Django Channelsi mõistmine
Django Channels laiendab Django võimekust traditsioonilisest päringu-vastuse tsüklist kaugemale, võimaldades asünkroonset suhtlust ja püsivaid ühendusi. See saavutatakse Asynchronous Server Gateway Interface (ASGI) kasutuselevõtuga, mis on Django traditsioonilise sünkroonse liidese WSGI (Web Server Gateway Interface) vaimne järeltulija.
Põhimõisted
- ASGI (Asynchronous Server Gateway Interface): ASGI on standardne liides asünkroonsete Pythoni veebirakenduste ja serverite vahel. See võimaldab Djangol käsitleda pikaajalisi ühendusi, nagu WebSocketid, mis jäävad avatuks pikemaks ajaks.
- Channels-kihid (Channels Layers): Channels-kihid pakuvad suhtluse selgroogu sõnumite jaotamiseks teie rakenduse erinevate osade vahel. Mõelge sellest kui sõnumijärjekorrast või pub/sub süsteemist. Levinumad implementatsioonid hõlmavad Redist, arenduseks mõeldud mälusisest kihti ja pilvepõhiseid sõnumiteenuseid.
- Consumerid (Consumers): Consumerid on Django vaadete asünkroonsed vasted. Nad käsitlevad sissetulevaid sõnumeid ja teostavad toiminguid sõnumi sisu alusel. Consumereid saab kirjutada funktsioonide või klassidena, pakkudes paindlikkust ja taaskasutatavust.
- Marsruutimine (Routing): Marsruutimine määratleb, kuidas sissetulevad sõnumid suunatakse konkreetsetele consumeritele. See sarnaneb Django URL-i marsruutimisega, kuid on mõeldud WebSocket-ühenduste jaoks.
Django projekti seadistamine Channelsiga
Alustame Django projekti seadistamisest ja Django Channelsi paigaldamisest. See jaotis eeldab, et teil on Python ja Django paigaldatud.
1. Looge uus Django projekt
Avage oma terminal ja looge uus Django projekt:
django-admin startproject myproject
cd myproject
2. Looge virtuaalkeskkond (soovitatav)
Alati on hea tava luua virtuaalkeskkond, et isoleerida oma projekti sõltuvused:
python3 -m venv venv
source venv/bin/activate # Linuxis/macOS-is
.\venv\Scripts\activate # Windowsis
3. Paigaldage Django Channels
Paigaldage Django Channels ja selle sõltuvused, kasutades pip-i:
pip install channels daphne
Daphne on ASGI server, mida me kasutame oma Channelsi rakenduse käivitamiseks. Teised ASGI serverid, nagu uvicorn, on samuti ühilduvad.
4. Konfigureerige Django seaded
Avage oma projekti `settings.py` fail ja lisage `channels` `INSTALLED_APPS` nimekirja:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
# Teie teised rakendused
]
Lisage ASGI rakenduse konfiguratsioon `settings.py` faili:
ASGI_APPLICATION = 'myproject.asgi.application'
See ütleb Djangole, et ta kasutaks ASGI rakendust, mis on defineeritud `myproject/asgi.py` failis.
5. Konfigureerige Channelsi kiht
Konfigureerige Channelsi kiht `settings.py` failis. Arenduseks võite kasutada mälusisest kihti. Tootmiskeskkonnas on Redis levinud valik. Selles näites kasutame Redist. Veenduge, et Redis on teie süsteemis paigaldatud ja töötab.
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
Kui teil pole `channels_redis` paigaldatud, paigaldage see:
pip install channels_redis
6. Looge asgi.py
Kui see ei eksisteeri, looge oma projekti kausta `asgi.py` fail (kõrvuti `wsgi.py` failiga). See fail defineerib ASGI rakenduse:
# myproject/asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing # Importige oma rakenduse marsruutimine
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
Lihtsa vestlusrakenduse ehitamine
Ehitame lihtsa vestlusrakenduse, et demonstreerida Django Channelsi ja WebSocketeid. See näide võimaldab kasutajatel saata ja vastu võtta sõnumeid ühes vestlusruumis.
1. Looge uus Django rakendus
Looge uus Django rakendus nimega `chat`:
python manage.py startapp chat
Lisage `chat` `INSTALLED_APPS` nimekirja `settings.py` failis:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'chat',
# Teie teised rakendused
]
2. Defineerige WebSocketi marsruutimine
Looge `chat` rakenduses `routing.py` fail, et defineerida WebSocketi marsruutimine:
# chat/routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
See defineerib marsruudi WebSocketi ühendustele aadressil `/ws/chat/
3. Looge Consumer
Looge `chat` rakenduses `consumers.py` fail, et defineerida `ChatConsumer`:
# chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async
from django.contrib.auth.models import User
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = f'chat_{self.room_name}'
# Liitu toa grupiga
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Lahku toa grupist
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Sõnumi vastuvõtmine WebSocketist
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
username = text_data_json['username'] # Eemaldage kasutajanimi vastuvõetud andmetest
# Saada sõnum toa grupile
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat.message',
'message': message,
'username': username,
}
)
# Sõnumi vastuvõtmine toa grupist
async def chat_message(self, event):
message = event['message']
username = event['username']
# Saada sõnum WebSocketile
await self.send(text_data=json.dumps({
'message': message,
'username': username,
}))
See consumer käsitleb WebSocketi ühendusi, liitub vestlusruumidega ja lahkub neist, võtab klientidelt vastu sõnumeid ja edastab sõnumeid toa grupile. Oluline on, et see on asünkroonne, mis võimaldab tal käsitleda mitut ühendust samaaegselt.
4. Looge lihtne mall (template)
Looge oma projektis fail `templates/chat/room.html`. Teil võib olla vaja luua `templates` kaust oma projekti juurkausta ja seejärel `chat` kaust selle sisse. See mall kuvab vestlusruumi ja võimaldab kasutajatel sõnumeid saata.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Vestlusruum</title>
</head>
<body>
<h1>Vestlusruum: {{ room_name }}</h1>
<div id="chat-log"></div>
<input type="text" id="chat-message-input" size="100"/><br/>
<input type="text" id="chat-username-input" size="100" placeholder="Sisestage oma kasutajanimi"/><br/>
<button id="chat-message-submit">Saada</button>
<script>
const roomName = {{ room_name|json_script:"room-name" }};
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/chat/'
+ roomName
+ '/'
);
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
document.querySelector('#chat-log').value += (data.username + ': ' + data.message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#chat-message-input').focus();
document.querySelector('#chat-message-input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#chat-message-submit').click();
}
};
document.querySelector('#chat-message-submit').onclick = function(e) {
const messageInputDom = document.querySelector('#chat-message-input');
const usernameInputDom = document.querySelector('#chat-username-input');
const message = messageInputDom.value;
const username = usernameInputDom.value; // Hangi kasutajanimi
chatSocket.send(JSON.stringify({
'message': message,
'username': username
}));
messageInputDom.value = '';
};
</script>
</body>
</html>
See mall kasutab JavaScripti WebSocketi ühenduse loomiseks, sõnumite saatmiseks ja vastuvõetud sõnumite kuvamiseks `chat-log` elemendis. Nüüd sisaldab see ka kasutajanime sisestusvälja ja saadab kasutajanime iga sõnumiga kaasa.
5. Looge vaade (view)
Looge `chat` rakenduses `views.py` fail, et defineerida vaade, mis renderdab vestlusruumi malli:
# chat/views.py
from django.shortcuts import render
def room(request, room_name):
return render(request, 'chat/room.html', {
'room_name': room_name
})
6. Defineerige URL-mustrid
Lisage vestlusrakenduse URL-id oma projekti `urls.py` faili:
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('chat/', include('chat.urls')),
]
Looge `chat` rakenduses `urls.py` fail:
# chat/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<str:room_name>/', views.room, name='room'),
]
7. Käivitage arendusserver
Käivitage Django arendusserver Daphne'iga:
python manage.py runserver
Avage oma veebibrauser ja navigeerige aadressile `http://127.0.0.1:8000/chat/myroom/` (asendage `myroom` soovitud vestlusruumi nimega). Peaksite nägema vestlusruumi liidest. Avage sama URL teises brauseriaknas, et simuleerida mitut kasutajat.
Edasijõudnute tehnikad ja parimad tavad
Nüüd, kui teil on toimiv lihtne vestlusrakendus, uurime mõningaid edasijõudnute tehnikaid ja parimaid tavasid robustsete ja skaleeritavate reaalajas rakenduste ehitamiseks Django Channelsiga.
Autentimine ja autoriseerimine
Teie WebSocketi ühenduste turvamine on ülioluline. Django Channels pakub sisseehitatud tuge autentimiseks ja autoriseerimiseks. Saate kasutada Django standardset autentimissüsteemi kasutajate autentimiseks enne WebSocketiga ühendumist. `AuthMiddlewareStack` teie `asgi.py` failis autentib kasutajad automaatselt nende seansi põhjal. Saate autentitud kasutajale ligi oma consumeris `self.scope['user']` kaudu.
Näide:
# chat/consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
user = self.scope['user']
if user.is_authenticated:
await self.accept()
else:
await self.close()
Keerukamate autoriseerimisstsenaariumide jaoks saate implementeerida kohandatud vahevara või kontrolle oma consumerites.
Skaleeritavus ja jõudlus
Kui teie rakendus kasvab, muutub skaleeritavus kriitiliseks mureks. Django Channels on loodud skaleeritavaks, kuid peate arvestama mitmete teguritega:
- Channels-kiht: Valige robustne ja skaleeritav Channels-kiht, näiteks Redis või pilvepõhine sõnumiteenus nagu Amazon MQ või Google Cloud Pub/Sub. Redis on hea alguspunkt, kuid suure liiklusega rakenduste jaoks kaaluge hallatud pilvelahendust.
- ASGI server: Kasutage tootmiskeskkonnale sobivat ASGI serverit nagu Daphne või Uvicorn. Need serverid on loodud suure hulga samaaegsete ühenduste tõhusaks haldamiseks.
- Horisontaalne skaleerimine: Paigutage mitu oma Django rakenduse instantsi koormusjaoturi taha, et töökoormust jaotada. Iga instants peaks ühenduma sama Channels-kihiga.
- Andmebaasi optimeerimine: Kui teie rakendus hõlmab andmebaasi interaktsioone, optimeerige oma andmebaasi päringuid ja kaaluge vahemälu kasutamist andmebaasi koormuse vähendamiseks.
Testimine
Teie Channelsi rakenduste testimine on nende usaldusväärsuse ja korrektsuse tagamiseks hädavajalik. Django Channels pakub testimisvahendeid WebSocketi ühenduste simuleerimiseks ja teie consumerite käitumise kontrollimiseks.
Näide:
# chat/tests.py
import pytest
from channels.testing.websocket import WebsocketCommunicator
from chat.consumers import ChatConsumer
@pytest.mark.asyncio
async def test_chat_consumer():
communicator = WebsocketCommunicator(ChatConsumer.as_asgi(), "ws/chat/testroom/")
connected, subprotocol = await communicator.connect()
assert connected
await communicator.send_to(text_data={"message": "Hello", "username": "TestUser"})
response = await communicator.receive_from()
assert response == '{"message":"Hello","username":"TestUser"}'
await communicator.disconnect()
See näide kasutab `WebsocketCommunicator`-it, et simuleerida WebSocketi ühendust `ChatConsumer`-iga, saadab sõnumi ja kontrollib vastust.
Vigade käsitlemine
Robustne vigade käsitlemine on rakenduse krahhide vältimiseks ja hea kasutajakogemuse pakkumiseks ülioluline. Implementeerige oma consumerites korralik vigade käsitlemine erandite püüdmiseks ja ootamatute olukordade sujuvaks haldamiseks. Saate kasutada `try...except` plokke erandite püüdmiseks ja klientidele veateadete saatmiseks.
Näide:
# chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def receive(self, text_data):
try:
text_data_json = json.loads(text_data)
message = text_data_json['message']
username = text_data_json['username']
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat.message',
'message': message,
'username': username
}
)
except Exception as e:
await self.send(text_data=json.dumps({
'error': str(e)
}))
Paigaldamise kaalutlused
Django Channelsi rakenduste paigaldamine nõuab hoolikat planeerimist ja kaalutlemist. Siin on mõned olulised aspektid, mida meeles pidada:
- ASGI server: Kasutage tootmistasemel ASGI serverit nagu Daphne või Uvicorn. Konfigureerige server suure hulga samaaegsete ühenduste haldamiseks ja jõudluse optimeerimiseks.
- Channels-kiht: Valige usaldusväärne ja skaleeritav Channels-kiht. Redis on hea valik väikestele ja keskmise suurusega rakendustele, kuid suuremate rakenduste puhul kaaluge pilvepõhist sõnumiteenust. Veenduge, et teie Channels-kiht on korralikult konfigureeritud ja turvatud.
- Koormuse jaotamine: Kasutage koormusjaoturit liikluse jaotamiseks mitme Django rakenduse instantsi vahel. See parandab jõudlust ja tagab kõrge kättesaadavuse.
- Monitooring: Implementeerige põhjalik monitooring oma rakenduse jõudluse jälgimiseks ja võimalike probleemide tuvastamiseks. Jälgige aktiivsete WebSocketi ühenduste arvu, sõnumite läbilaskevõimet ja vigade määra.
- Turvalisus: Turvake oma WebSocketi ühendused SSL/TLS krüpteeringu abil. Implementeerige korralikud autentimis- ja autoriseerimismehhanismid, et kaitsta oma rakendust volitamata juurdepääsu eest.
Kasutusjuhud peale vestlusrakenduste
Kuigi meie näide keskendus vestlusrakendusele, on Django Channels mitmekülgne ja seda saab rakendada laiale valikule reaalajas rakendustele. Siin on mõned näited:
- Reaalajas andmete armatuurlauad: Kuvage reaalajas andmete uuendusi armatuurlaudadel süsteemi jõudluse, finantsturgude või sotsiaalmeedia trendide jälgimiseks. Näiteks finantskauplemisplatvorm võiks kasutada Django Channelsit, et edastada kasutajatele reaalajas aktsiahindu.
- Koostöö-redigeerimisvahendid: Võimaldage mitmel kasutajal samaaegselt redigeerida dokumente, arvutustabeleid või koodi, kus muudatused kajastuvad reaalajas. Mõelge koostööpõhisele dokumendiredigeerimisplatvormile sarnaselt Google Docsile.
- Online-mängud: Ehitage mitme mängijaga mänge, kus mängijate vahel toimub reaalajas interaktsioon. See võib ulatuda lihtsatest lauamängudest keerukate põnevusmängudeni.
- Reaalajas teavitused: Saatke kasutajatele reaalajas teavitusi sündmuste, uuenduste või hoiatuste kohta. Näiteks e-kaubanduse platvorm võiks teavitada kasutajaid, kui nende tellimuse staatus muutub.
- IoT (Asjade Internet) rakendused: Koguge ja töödelge andmeid IoT seadmetest reaalajas. Kujutage ette nutikodu rakendust, mis saab andurite andmeid erinevatelt seadmetelt ja uuendab vastavalt kasutajaliidest.
Kokkuvõte
Django Channels pakub võimsat ja paindlikku raamistikku reaalajas rakenduste ehitamiseks Pythoni ja Djangoga. Kasutades WebSocketeid, ASGI-d ja Channels-kihte, saate luua väga interaktiivseid ja kaasahaaravaid kasutajakogemusi. See juhend on andnud põhjaliku ülevaate Django Channelsist, käsitledes põhimõisteid, praktilist näidet ja edasijõudnute tehnikaid. Django Channelsit edasi uurides avastate selle tohutu potentsiaali uuenduslike ja mõjukate reaalajas rakenduste ehitamiseks.
Võtke omaks asünkroonse programmeerimise jõud ja avage oma Django projektide täielik potentsiaal Django Channelsiga!